<?php


namespace chick1993\util;


use chick1993\util\libs\exceptions\RuntimeException;

/**
 * Class Curl
 * @package chick1993\curl
 */
class Curl
{
    /**
     * @var string 返回结果
     */
    private $result;

    /**
     * 发起GET请求
     * @param string $url 请求地址
     * @param array $options CURL参数
     * @return self
     * @throws RuntimeException
     */
    static public function get(string $url, array $options = []): self
    {
        $options[CURLOPT_POST] = 0;
        return self::send($url, $options);
    }

    /**
     * 发起POST请求
     * @param string $url 请求地址
     * @param mixed $data POST数据
     * @param array $options CURL参数
     * @return self
     * @throws RuntimeException
     */
    static public function post(string $url, $data = '', array $options = []): self
    {
        if (!is_string($data)) {
            $data = http_build_query($data);
        }
        $options[CURLOPT_POST] = 1;
        $options[CURLOPT_POSTFIELDS] = $data;
        return self::send($url, $options);
    }

    /**
     * 发起POST请求
     * @param string $url 请求地址
     * @param string|array $data POST数据
     * @param array $options CURL参数
     * @return self
     * @throws RuntimeException
     */
    static public function postJson(string $url, $data = '', array $options = []): self
    {
        if (!is_string($data)) {
            $data = json_encode($data);
        }
        $options[CURLOPT_HTTPHEADER][] = 'Content-Type: application/json; charset=utf-8';
        $options[CURLOPT_POST] = 1;
        $options[CURLOPT_POSTFIELDS] = $data;
        return self::send($url, $options);
    }

    /**
     * 发起请求
     * @param string $url 请求地址
     * @param array $options CURL参数，[key=>value,key=>value...]
     * @return self
     * @throws RuntimeException
     */
    static public function send(string $url, array $options = []): self
    {
        $defOpt = [
            CURLOPT_TIMEOUT => 3,
            CURLOPT_HEADER => 0,
            CURLOPT_SSL_VERIFYPEER => false,//不验证证SSL书
            CURLOPT_SSL_VERIFYHOST => false,//不验证证SSL书
            CURLOPT_RETURNTRANSFER => 1,//以文件流形式返回数据
        ];
        $opts = $options + $defOpt;
        $ch = curl_init($url);
        curl_setopt_array($ch, $opts);
        $data = curl_exec($ch);
        $errno = curl_errno($ch);
        $err = curl_strerror($errno);
        curl_close($ch);

        if ($errno !== CURLE_OK) {
            throw new RuntimeException("Curl Error: $err", $errno);
        }

        is_bool($data) && $data = $data ? 'true' : 'false';
        $self = new self();
        $self->result = (string)$data;
        return $self;
    }

    /**
     * 获取原始返回值
     * @return string
     */
    public function getOrigin(): string
    {
        return $this->result;
    }

    /**
     * 将返回值转为数组
     * @return array
     * @throws RuntimeException
     */
    public function toArray(): array
    {
        $data = $this->getOrigin();

        $data = json_decode($data, true);
        $errno = json_last_error();
        if ($errno !== JSON_ERROR_NONE) {
            $err = json_last_error_msg();
            throw new RuntimeException("Curl: Json Error: {$err}", $errno);
        }

        if (empty($data)) $data = [];

        if (!is_array($data)) {
            throw new RuntimeException("Curl: 数据转为数组失败");
        }

        return $data;
    }
}